package com.fly.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.annotation.NonNull;
import android.util.Xml;

import com.fly.db.entity.DBEntity;
import com.fly.db.entity.Table;
import com.fly.db.exception.DBInitException;
import com.fly.db.util.TableUtil;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created with Android Studio.
 * Package_Name：com.fly.db
 * Project_Name：DBExample
 * User：郭鹏飞
 * Date：2015/12/17
 * Email：love518420@foxmail.com
 * Description：
 */
public class FlySQLiteOpenHelper extends SQLiteOpenHelper {

    private static FlySQLiteOpenHelper instance = null;

    private static String DB_NAME;
    private static int DB_VERSION;

    // 线程安全的计数器 用来记录当前数据库打开的连接数量
    private AtomicInteger dbCount;
    // 数据库执行
    private SQLiteDatabase db = null;
    private DBEntity dbEntity;

    private OnUpgradeListener upgradeListener;

    public static void initDB(Context context) throws DBInitException {
        try {
            InputStream is = context.getAssets().open("db_config.xml");
            XmlPullParser xmlPullParser = Xml.newPullParser();
            xmlPullParser.setInput(is, "UTF-8");
            int eventType = xmlPullParser.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {

                switch (eventType) {
                    case XmlPullParser.START_TAG:
                        String tag = xmlPullParser.getName();
                        if (tag.equals("dbName")) {
                            DB_NAME = xmlPullParser.nextText();
                        } else if (tag.equals("dbVersion")) {
                            DB_VERSION = Integer.parseInt(xmlPullParser.nextText());
                        }
                        break;
                }

                eventType = xmlPullParser.next();
            }
        } catch (IOException | XmlPullParserException e) {
            throw new DBInitException();
        }
    }

    public FlySQLiteOpenHelper(Context context,  DBEntity dbEntity) {
        super(context, DB_NAME, null, DB_VERSION);
        this.dbEntity = dbEntity;
        dbCount = new AtomicInteger();
    }

    public static FlySQLiteOpenHelper getInstance(@NonNull Context context,
                                                  @NonNull DBEntity dbEntity) {
        if (instance == null) {
            synchronized (FlySQLiteOpenHelper.class) {
                if (instance == null) {
                    TableUtil.initDBEntity(dbEntity);
                    instance = new FlySQLiteOpenHelper(context, dbEntity);
                }
            }
        }
        return instance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        for (Table table : dbEntity.getTables()) {
            TableUtil.createTable(db, table.getTableName(), table.getColumns());
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO: 2015/12/17 数据库更新操作
        /**
         * 这个地方有俩种操作
         * 1. 更新数据表
         * 2. 删除重建 （针对指定表操作，指针整个数据库操作-回调onCreate即可）
         *
         * 对比
         * 第二种操作会丢失数据
         * 2.1 比较推荐的做法 只针对指定表进行操作
         * 2.2 回调onCreate 如果数据库中有多张表，需要全部删除，没有必要（只升级部分表）
         * 第一种操作比较复杂
         */
        if (upgradeListener != null) {
            upgradeListener.onUpgrade(db, oldVersion, newVersion);
        }
    }

    /**
     * 打开数据库
     *
     * @return SQLiteDatabase
     */
    public synchronized SQLiteDatabase openDatabase() {
        // 如果 首次打开数据库连接 获取实例对象计数器+1 否则直接返回对象实例
        if (dbCount.incrementAndGet() == 1) {
            if (db == null) {
                db = getWritableDatabase();
            }
        }
        return db;
    }

    /**
     * 关闭数据库
     */
    public synchronized void closeDatabase() {
        // 如果 数据库连接都不再被使用 则关闭数据库连接 每次请求关闭数据库计数器-1知道为0的时候关闭
        if (dbCount.decrementAndGet() == 0) {
            close();
            db = null;
        }
    }

    public void setOnUpgradeListener(OnUpgradeListener upgradeListener) {
        this.upgradeListener = upgradeListener;
    }

    public interface OnUpgradeListener {
        void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
    }

}
